#include "FDBFile.h"
#include "OCMain/StringConverter.h"
#include "OCMain/DataStream.h"

namespace OCPP
{
#define maxFDBFileSize 4294967296
	FDBFile::FDBFile(String name)
		:mName(name),
		mW(false),
		mP(0)
	{
	
	}

	FDBFile::~FDBFile()
	{
		
	}

	void FDBFile::open()
	{
		for (int i = 0; i < 1000; i++)
		{
			String filenameData = mName + String(".f") + StringConverter::toString(mIfsCapacityList.size());
			std::ifstream ifs(filenameData.c_str(), std::ios::binary);
			if (ifs)
			{
				ifs.seekg(0, std::ios::end);
				size_t s = ifs.tellg();
				mIfsCapacityList.push_back(s);
				mP += s;
				ifs.seekg(0);
			}
			else
			{
				break;
			}
		}
	}

	bool FDBFile::write(char* ptr, size_t e)
	{
		if (!mW)
		{
			openForWrite();
			if (!mW)
			{
				return false;
			}
		}

		mWriteStream.seekp(0, std::ios::end);
		std::ostream& os = mWriteStream.write(ptr, e);
		if (!os)
		{
			return false;
		}

		mP += e;

		mWriteStream.flush();
		if (mWriteStream.tellp() > maxFDBFileSize)
		{
			mWriteStream.close();
			mW = false;
		}

		return true;
	}

	void FDBFile::openForWrite()
	{
		mW = false;
		for (int i = 0; i < 1000; i++)
		{
			String filenameData = mName + String(".f") + StringConverter::toString(i);
			if (FileUtil::sizeOfFile(filenameData) < maxFDBFileSize)
			{
				mWriteStream.open(filenameData.c_str(), std::ios::app | std::ios::ate | std::ios::binary);
				if (mWriteStream)
				{
					mW = true;
				}
				break;
			}
		}
	}

	MemoryDataStreamPtr FDBFile::read(size_t b, size_t e)
	{
		MemoryDataStreamPtr dataStream;
		String filenameData;

		size_t c = 0;
		for (size_t i = 0; i < mIfsCapacityList.size(); i++)
		{
			size_t s = mIfsCapacityList[i];
			c += s;
			if (b < c)
			{
				c -= s;
				filenameData = mName + String(".f") + StringConverter::toString(i);
				break;
			}
		}
		if (!filenameData.empty())
		{
			std::ifstream ifs(filenameData.c_str(), std::ios::binary);
			if (ifs)
			{
				dataStream = MemoryDataStreamPtr(new MemoryDataStream(e));
				ifs.seekg(b - c, std::ios::beg);
				ifs.read((char*)dataStream->getPtr(), e);
				ifs.close();
			}
		}

		return dataStream;
	}
}

